﻿using System;
using System.Collections;
using System.Drawing;
using System.Security.Cryptography;
using System.Text;
using MySql.Data.MySqlClient;

/*******************************
 * Author:  Jeremi Stadler
 * Starded: 2009 desember
 * 
 * <START><1>this is the text that the first note contains./,\257,281,3,2,color1,color2,color3,color4<END>
 * 
 * 
 *******************************/
namespace StickTops
{

    public class BaseSave
    {
        protected static NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();

        protected String FormsToString()
        {
            string savingString = "";
            int iNumberOfForms = 0;
            try
            {
                foreach (StickTop i in MainForm.Instance.GetNotes())
                {
                    if (i.MainText() != "")
                    {
                        if (i.MainText().IndexOf(@"endl1995") >= 0)
                        {
                            System.Windows.Forms.MessageBox.Show(@"Sorry... The endl1995 combination is not allowed...");
                            return "";
                        }
                        savingString += i.MainText() + @"endl1995" + i.Size.Width + "," + i.Size.Height + "," + i.Location.X + "," + i.Location.Y + "," + i.GetColors() + @"<NEXT>";
                        iNumberOfForms++;
                        
                    }
                }

                savingString = "<START><" + iNumberOfForms.ToString() + ">" + savingString + "<END>";

            }
            catch (Exception e)
            {
                log.Error("FormsToString-Exception: "+ e.Message);
                return "";
            }
            return savingString;

        }

        protected Boolean StringToForms(string LoadingString)
        {
            try
            {
                LoadingString = LoadingString.Substring(7);//The start parameter
                int iNumbers = int.Parse(LoadingString.Substring(1, LoadingString.IndexOf('>') - 1)); //Numbers of forms
                LoadingString = LoadingString.Substring(LoadingString.IndexOf('>') + 1);//Take away the start and numbers of forms parameters

                for (int i = 0; iNumbers > i; i++)//for each form: make new form
                {
                    string stickText = LoadingString.Substring(0, LoadingString.IndexOf(@"endl1995"));//the end of text sign
                    string stickSizes = LoadingString.Substring(LoadingString.IndexOf(@"endl1995") + 8, LoadingString.IndexOf(@"<NEXT>") - LoadingString.IndexOf(@"endl1995") - 8);
                    string[] stickSizesArr = stickSizes.Split(',');//get the forms size and position

                    //Make the Size and Pos varables
                    Size stickSize = new Size(int.Parse(stickSizesArr[0]), int.Parse(stickSizesArr[1]));
                    Point stickPos = new Point(int.Parse(stickSizesArr[2]), int.Parse(stickSizesArr[3]));

                    Color lblFore;
                    Color lblBack;
                    Color mainFore;
                    Color mainBack;
                    

                    if (stickSizesArr.Length == 4)
                    {
                        lblFore = Properties.Settings.Default.LabelFore;
                        lblBack = Properties.Settings.Default.LabelBack;
                        mainFore = Properties.Settings.Default.MainFore;
                        mainBack = Properties.Settings.Default.MainBack;


                    }
                    else
                    {
                        lblFore = Color.FromArgb(int.Parse(stickSizesArr[4]));
                        lblBack = Color.FromArgb(int.Parse(stickSizesArr[5]));
                        mainFore = Color.FromArgb(int.Parse(stickSizesArr[6]));
                        mainBack = Color.FromArgb(int.Parse(stickSizesArr[7]));
                    }

                    NewNote newNote = new NewNote(stickText, stickSize, stickPos, mainFore, mainBack, lblFore, lblBack);

                    //Make the new note!
                    MainForm.Instance.MakeNewNote(newNote);

                    //Prepare for the next one
                    LoadingString = LoadingString.Substring(LoadingString.IndexOf("<NEXT>") + 6);
                }
            }
            catch (Exception e)
            {
                log.Error("StringToForms-Exception: "+ e.Message);
                return false;
            }
            return true;

        }

    }

    
    public class SaveFileObselete : BaseSave
    {

        public SaveFileObselete()
        {

        }



        public Boolean SaveToFile()
        {
            System.IO.FileStream FileWriter;
            try
            {
                FileWriter = new System.IO.FileStream(System.Windows.Forms.Application.StartupPath + @"StickNotesSaving.txt", System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite);
                byte[] savingArr = System.Text.Encoding.Unicode.GetBytes(FormsToString());

                FileWriter.Write(savingArr, 0, savingArr.Length);
                FileWriter.Flush();
                FileWriter.Dispose();
            }
            catch (Exception e)
            {
                log.Error("SaveToFile-Exception: "+ e.Message);
                return false;
            }

            return true;
        }

        public Boolean LoadFromFile()
        {
            string LoadingString;
            System.IO.StreamReader FileReader;
            try
            {
                FileReader = new System.IO.StreamReader(System.Windows.Forms.Application.StartupPath + @"StickNotesSaving.txt", Encoding.Unicode);
                LoadingString = FileReader.ReadToEnd();

                //Do simple checking
                if (LoadingString.IndexOf("<START>") < 0) //the file is corrupt
                {
                    return false;
                }

                //Return the Result
                return StringToForms(LoadingString);

            }
            catch (Exception e) 
            { 
                log.Error("LoadFormFile-Exception: "+ e.Message);
                return false;
            }

        }

    }

    public class SaveSql : BaseSave
    {
        private string message = "";
        private LogInState state = LogInState.Working;
        private MySqlConnection Conn;


        public SaveSql()
        {
            Conn = new MySqlConnection("Connection Timeout=5;Server=disk-one.se;Database=jeremi_sticktops;Uid=jeremi;Pwd=FyZj7yWWVe4TNXAp");
        }


        public enum LogInState { Success, WrongPass, WrongUserName, ConnError, OtherError, Working, CorruptString, UserExists }

        public string Message { get { return message; } }

        public LogInState State { get { return state; } }



        public Boolean Save(string username)
        {
            string SQL;
            try
            {
                //Get the forms to a string
                string SendString = FormsToString();

                //prepare the Query
                SQL = @"UPDATE users SET sticktop='"+MySqlHelper.EscapeString(SendString)+"' WHERE username='"+username +"'";

                // Open connection
                if (Conn.State != System.Data.ConnectionState.Open) { Conn.Open(); }

                //Make the connection string
                MySqlCommand command = new MySqlCommand(SQL, Conn);
                
                command.ExecuteNonQuery();
                Conn.Close();
                //Change State
                this.state = LogInState.Success;
            }
            catch (MySqlException e)
            {
                log.Error("SqlSave-MySqlException: "+ e.Message);
                message = "Connection problem";
                state = LogInState.ConnError;
                return false;
            }
            catch (Exception e)
            {
                log.Error("SqlSave-Exception: "+ e.Message);
                message = e.Message;
                state = LogInState.OtherError;
                return false;
            }
            finally { if (Conn.State == System.Data.ConnectionState.Open) { Conn.Close(); } }

            return true;

        }

        public Boolean LogIn(string username, string password)
        {
            bool makeForms = false;
            try
            {

                uint UserId = 0;
                string UserString = "";
                object UserObject;


                string UserMd5Pass = EncodePassword(password);

                // Open connection
                if (Conn.State != System.Data.ConnectionState.Open) { Conn.Open(); }

                MySqlCommand command = new MySqlCommand("SELECT id FROM users WHERE username='" + username + "'", Conn);
                UserObject = command.ExecuteScalar(); //Returns null if the user does not exist

                if (UserObject == null) // The user does not exist
                {
                    Conn.Close();
                    state = LogInState.WrongUserName;
                    message = "Wrong Username";
                    return false;
                }

                UserId = uint.Parse(UserObject.ToString());
                UserObject = null;

                MySqlCommand command2 = new MySqlCommand("SELECT sticktop FROM users WHERE id='" + UserId + "' AND md5='" + UserMd5Pass + "'", Conn);
                UserObject = command2.ExecuteScalar();

                if (UserObject == null) 
                {
                    Conn.Close();
                    state = LogInState.WrongPass;
                    message = "Wrong Password";
                    return false;
                }

                Conn.Close();

                //Get the Forms string from the object
                UserString = UserObject.ToString();

                //Make the Forms
                makeForms = StringToForms(UserString);

                if (makeForms)
                {
                    //Change State
                    this.state = LogInState.Success;
                }
                else
                {
                    this.state = LogInState.CorruptString;
                }

            }
            catch (MySqlException e)         // Connection problem
            {
                log.Error("LogIn-MySqlException: " + e.Message);
                state = LogInState.ConnError;
                message = "Could not connect to server";
                return false;
            }

            catch (Exception e)            // Other problem
            {
                log.Error("LogIn-Exception: "+e.Message);
                state = LogInState.OtherError;
                message = e.Message;
                return false;
            }
            finally {  Conn.Close(); }

            return makeForms;
        }

        public Boolean CreateUser(string username, string password)
        {
            try
            {
                string md5Pass = EncodePassword(password);
                object UserObject;

                // Open connection
                if (Conn.State != System.Data.ConnectionState.Open) { Conn.Open(); }

                //Make query
                MySqlCommand command1 = new MySqlCommand("SELECT id FROM users WHERE username='" + username + "'", Conn);

                UserObject = command1.ExecuteScalar();

                if (UserObject != null)// The user does already exist
                {
                    state = LogInState.UserExists;
                    message = "The User does already exist";
                    Conn.Close();
                    return false;
                }

                //Make query
                MySqlCommand command2 = new MySqlCommand("INSERT INTO users (username,password,md5,sticktop) VALUES ('" + username + "','" + password + "','" + md5Pass + "','<START><1>endl1995360,240,500,300<NEXT><END>')", Conn);// oldPos=360,240,789,240

                //Execute query
                command2.ExecuteNonQuery();
                Conn.Close();
                command2.Dispose();
                md5Pass = null;
                state = LogInState.Success;
            }

            catch (MySqlException e)
            {
                log.Error("CreateUser-MySQLException: " + e.Message);
                message = e.Message;
                state = LogInState.ConnError;
            }

            catch (Exception e)
            {
                log.Error("CreateUser-Exception: " + e.Message);
                message = e.Message;
                state = LogInState.OtherError;
                return false;
            }
            return true;
        }

        public string EncodePassword(string originalPassword)
        {
            //Declarations
            Byte[] originalBytes;
            Byte[] encodedBytes;
            MD5 md5;
            string md5String;


            //Instantiate MD5CryptoServiceProvider, get bytes for original password and compute hash (encoded password)
            md5 = new MD5CryptoServiceProvider();
            originalBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
            encodedBytes = md5.ComputeHash(originalBytes);

            md5String = BitConverter.ToString(encodedBytes);
            md5String.Replace("-", string.Empty);
            if (md5String.Length > 20)
            {
                md5String = md5String.Substring(0, 20);
            }
            encodedBytes = null;
            originalBytes = null;
            md5.Clear(); md5 = null;
            return md5String;
            }

    }
     

    public class NewNote
    {
        private Size stickSize;
        private Point stickPos;
        private Color textFore;
        private Color textBack;
        private Color labelFore;
        private Color labelBack;
        private string mainText;

        public NewNote(string text,Size size,Point pos,Color textfore,Color textback,Color lblfore,Color lblback)
        {
            mainText = text;
            stickSize = size;
            stickPos = pos;
            textFore = textfore;
            textBack = textback;
            labelFore = lblfore;
            labelBack = lblback;
        }

            public string MainText { get { return mainText; } }
            public Color MainFore { get { return textFore;} }
            public Color MainBack { get { return textBack;} }
            public Color LabelFore { get { return labelFore;} }
            public Color LabelBack { get { return labelBack;} }
            public Size Size { get { return stickSize;} }
            public Point Pos { get { return stickPos;} }
        }

    public static class Vars
        {
            private static string username;
            private static string password;
            private static bool loggedin;

            public static string UserName { get { return username; } set { username = value; Properties.Settings.Default.Username = value; } }

            public static string PassWord { get { return password; } set { password = value; Properties.Settings.Default.Password = value; } }

            public static bool LoggedIn { get { return loggedin; } set { loggedin = value; } }

        }
    }
